# 版本: 1.0.2.20250825
# 作者: 陈振玺
# 功能: 箱线图绘制工具，支持显著性差异分析和可视化

r_vizcraft_boxplot_visualizer <- function(data_path, x_var, y_vars, output_dir = "./boxplot_output", plot_title = NULL, x_lab = NULL, y_lab = NULL) {
  # 检查必要包是否已安装
  required_packages <- c("readxl", "readr", "dplyr", "ggplot2", "ggpubr")
  for (pkg in required_packages) {
    if (!requireNamespace(pkg, quietly = TRUE)) {
      stop(paste0("包 ", pkg, " 未安装，请先安装该包"))
    }
  }
  
  # 根据文件扩展名读取数据
  if (grepl("\\.xlsx?$", data_path, ignore.case = TRUE)) {
    data <- readxl::read_excel(data_path)
  } else if (grepl("\\.csv$", data_path, ignore.case = TRUE)) {
    data <- readr::read_csv(data_path)
  } else {
    stop("不支持的文件格式，请提供Excel或CSV文件")
  }
  
  # 检查变量是否存在
  if (!(x_var %in% names(data))) {
    stop(paste0("X轴变量 ", x_var, " 不存在于数据中"))
  }
  
  # 创建输出目录
  if (!dir.exists(output_dir)) {
    dir.create(output_dir, recursive = TRUE)
  }
  
  # 为每个Y轴变量生成箱线图
  for (y_var in y_vars) {
    if (!(y_var %in% names(data))) {
      warning(paste0("Y轴变量 ", y_var, " 不存在于数据中，跳过"))
      next
    }
    
    # 过滤数据，确保变量为数值型
    plot_data <- data[, c(x_var, y_var)]
    names(plot_data) <- c("x", "y")
    plot_data <- plot_data[!is.na(plot_data$x) & !is.na(plot_data$y), ]
    
    # 设置默认标题和坐标轴标签
    if (is.null(plot_title)) {
      title <- paste0("箱线图: ", y_var)
    } else {
      title <- plot_title
    }
    
    if (is.null(x_lab)) {
      x_label <- x_var
    } else {
      x_label <- x_lab
    }
    
    if (is.null(y_lab)) {
      y_label <- y_var
    } else {
      y_label <- y_lab
    }
    
    # 创建基础箱线图
    p <- ggplot2::ggplot(plot_data, aes(x = x, y = y)) +
      ggplot2::geom_boxplot() +
      ggplot2::theme_minimal() +
      ggplot2::labs(title = title, x = x_label, y = y_label)
    
    # 进行显著性差异分析
    # 只有当X轴变量有多个分组时才进行分析
    if (length(unique(plot_data$x)) > 1) {
      # 使用ggpubr进行统计检验
      stat.test <- ggpubr::compare_means(y ~ x, data = plot_data, method = "wilcox.test")
      
      # 过滤显著性结果（P值≤0.05）
      sig.tests <- stat.test[stat.test$p <= 0.05, ]
      
      # 如果有显著性结果，则添加标记
      if (nrow(sig.tests) > 0) {
        # 添加统计标记
        p <- p + ggpubr::stat_compare_means(method = "wilcox.test", label = "p.signif")
      }
    }
    
    # 保存图形
    output_file <- file.path(output_dir, paste0(gsub("[^a-zA-Z0-9_]", "_", y_var), "_boxplot.png"))
    ggplot2::ggsave(output_file, plot = p, width = 8, height = 6, dpi = 300)
    cat(paste0("已保存箱线图到: ", output_file, "\n"))
  }
  
  cat("所有箱线图已生成完毕\n")
}

# 命令行参数解析
option_list <- list(
  optparse::make_option(c("-i", "--input"), type = "character", default = NULL,
                        help = "输入数据文件路径，支持Excel（.xlsx, .xls）或CSV（.csv）格式", metavar = "character"),
  optparse::make_option(c("-x", "--xvar"), type = "character", default = NULL,
                        help = "指定作为X轴的变量名", metavar = "character"),
  optparse::make_option(c("-y", "--yvars"), type = "character", default = NULL,
                        help = "指定一个或多个作为Y轴的变量名，多个变量用逗号分隔", metavar = "character"),
  optparse::make_option(c("-o", "--output"), type = "character", default = "./boxplot_output",
                        help = "指定输出图形的保存目录 [默认: %default]", metavar = "character"),
  optparse::make_option(c("-t", "--title"), type = "character", default = NULL,
                        help = "指定图形标题", metavar = "character"),
  optparse::make_option(c("--xlab"), type = "character", default = NULL,
                        help = "指定X轴标签", metavar = "character"),
  optparse::make_option(c("--ylab"), type = "character", default = NULL,
                        help = "指定Y轴标签", metavar = "character"),
  optparse::make_option(c("-h", "--help"), type = "logical", default = FALSE,
                        help = "显示帮助信息", metavar = "logical")
)

# 解析命令行参数
opt_parser <- optparse::OptionParser(option_list = option_list)
opt <- optparse::parse_args(opt_parser)

# 检查是否请求帮助
if (opt$help) {
  optparse::print_help(opt_parser)
  stop("显示帮助信息", call. = FALSE)
}

# 检查必需参数
if (is.null(opt$input)) {
  stop("错误: 必须指定输入文件路径 (-i, --input)")
}

if (is.null(opt$xvar)) {
  stop("错误: 必须指定X轴变量 (-x, --xvar)")
}

if (is.null(opt$yvars)) {
  stop("错误: 必须指定Y轴变量 (-y, --yvars)")
}

# 解析Y轴变量
y_vars <- unlist(strsplit(opt$yvars, ","))
y_vars <- gsub("^\\s+|\\s+$", "", y_vars)  # 去除首尾空格

# 调用主函数
r_vizcraft_boxplot_visualizer(
  data_path = opt$input,
  x_var = opt$xvar,
  y_vars = y_vars,
  output_dir = opt$output,
  plot_title = opt$title,
  x_lab = opt$xlab,
  y_lab = opt$ylab
)